namespace System
{
    public class RandomGaussian : Random
    {
        /*public static void Main(string[] args)
        {
            RandomGaussian gauss;
            if (args.Length > 0)
            {
                int seed = Int32.Parse(args[0]);
                gauss = new RandomGaussian(seed);
            }
            else
                gauss = new RandomGaussian();
            
            int n = 1000;
            double[] x = new double[n];
            for (int i = 0; i < n; i++)
            {
                x[i] = gauss.NextDouble();
                Console.WriteLine("{0} {1}", i, x[i]);
            }   
        }*/
            
        private static bool have_next;
        private static double next;
        
        public RandomGaussian() : base()
        {
            next = 0.0;
            have_next = false;
        }
        
        public RandomGaussian(int seed) : base(seed)
        {
            next = 0.0;
            have_next = false;
        }
        
        protected override double Sample()
        {
            if (have_next)
            {
                have_next = false;
                return next;
            }
            else
            {
                double x = 0.0;
                double y = 0.0;
                while (x == 0.0 || y == 0.0)
                {
                    x = base.Sample();
                    y = base.Sample();
                }
                next = Math.Sqrt(-2.0 * Math.Log(x)) * Math.Sin(2.0 * Math.PI * y);
                
                have_next = true;
                return Math.Sqrt(-2.0 * Math.Log(x)) * Math.Cos(2.0 * Math.PI * y);
            }
        }
    }
}
